import os

from loguru import logger
from ping3 import ping

from drive import ADB, UiAutomator2
from common import utils

CHECK_LOG_DIR = True


def sink(message):
    global CHECK_LOG_DIR
    log_dir = os.path.join(os.path.dirname(__file__), '../../data/log/')
    if CHECK_LOG_DIR:
        utils.make_dirs_if_not_exist(log_dir)
        CHECK_LOG_DIR = False
    ip = message.record["extra"].get('ip', 'adb')
    file_path = os.path.join(log_dir, '{}.log'.format(ip))
    with open(file_path, 'a') as file:
        file.write(message)


logger.add(sink)


class Driver(object):
    U2Instance = {}
    AdbInstance = {}

    def __init__(self, phone_ip):
        self.phone_ip = phone_ip

    def ping_ip(self):
        if not ping(self.phone_ip, timeout=1):
            raise Exception("phone ip={} can't connect".format(self.phone_ip))

    @property
    def adb(self) -> ADB:
        obj = BaseTask.AdbInstance.setdefault(self.phone_ip, ADB(self.phone_ip))
        obj.adb_connect(5)
        return obj

    @property
    def u2(self) -> U2Instance:
        obj = BaseTask.U2Instance.setdefault(self.phone_ip, UiAutomator2(self.phone_ip))
        obj.u2_connect()
        return obj

    @classmethod
    def all(cls):
        value = {
            'adb': BaseTask.AdbInstance.keys(),
            'ui_auto': BaseTask.U2Instance.keys()
        }
        return value


class BaseTask(object):
    AdbInstance = {}
    U2Instance = {}

    def __init__(self, phone, order_id):
        self.android_ip = phone
        self.adb = Driver(self.android_ip).adb
        self.u2 = Driver(self.android_ip).u2
        self.order_id = order_id
        self.current_page_attrib = []

    def raise_exception(self, msg):
        self.log_msg(msg, err_flag=True)
        self.u2.screenshot("{} {} {}".format(self.android_ip, self.order_id, msg))
        raise Exception(msg)

    def log_msg(self, msg, err_flag=False):
        msg = "order_id={}, msg={}".format(self.order_id, msg)
        if err_flag:
            logger.bind(ip=self.android_ip).warning(msg)
        else:
            logger.bind(ip=self.android_ip).info(msg)

    def click_text(self, text):
        for attrib in self.current_page_attrib:
            if attrib.get('text') == text:
                self.u2.click_text(text)
                return
            elif attrib.get('content-desc') == text:
                self.u2.click_description(text)
                return
        else:
            err_msg = 'click text={} failed, current_page_attrib={}'.format(text, self.current_page_attrib)
            self.raise_exception(err_msg)

    def click_bounds(self, bounds_str: str):
        bounds_temp = bounds_str.replace('[', ' ').replace(']', '').replace(',', ' ').strip()
        bounds = [int(i) for i in bounds_temp.split(' ')]
        x = int((bounds[2] - bounds[0]) / 2 + bounds[0])
        y = int((bounds[3] - bounds[1]) / 2 + bounds[1])
        self.log_msg("origin={}, bounds={}, x={}, y={}".format(bounds_str, bounds, x, y))
        self.adb.tap(x, y)

    def click_first_text(self, text):
        self.log_msg('即将点击 {}'.format(text))
        for attrib in self.current_page_attrib:
            if attrib.get('text') == text:
                self.click_bounds(attrib.get('bounds'))
                return
            elif attrib.get('content-desc') == text:
                self.click_bounds(attrib.get('bounds'))
                return
        else:
            err_msg = "click first text='{}' failed, current_page_attrib={}".format(text, self.current_page_attrib)
            self.raise_exception(err_msg)

    def unlock_phone(self):
        if not self.u2.check_screen_is_on():
            self.log_msg('即将点亮屏幕')
            self.u2.ui_auto2_unlock_screen()
